package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * @NAME: ThreadTest
 * @USER: wjj
 * @DATE: 2023/10/7
 * @TIME: 12:04
 * @DAY_NAME_FULL: 星期六
 * @PROJECT_NAME: gulimall
 */
public class ThreadTest {
    public static ExecutorService executor = Executors.newFixedThreadPool(10);//创建固定线程池，系统只有一两个

    public static void main(String[] args) throws ExecutionException, InterruptedException {

//         System.out.println("main......start.....");
//         Thread thread = new Thread01();
//         thread.start();
//         System.out.println("main......end.....");

//         Runable01 runable01 = new Runable01();
//         new Thread(runable01).start();

//         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
//         new Thread(futureTask).start();
//         System.out.println(futureTask.get());//等待线程完成，拿到返回结果
        //以上都不用，耗费资源
        //使用线程池

        /**
         *七大参数
         * 1、corePoolSize:[5] 核心线程数[一直存在，除非（alLowCoreThreadTimeOut）]，线程池，创建好以后就准备就绪的线程数量，就等待来接受异步任务去执行
         *          5个  Thread thread = new Thread();thread.start()
         * 2、maximumPoolSize[200];最大线程数量,控制资源
         * 3、keepAliveTime 存活时间,如果当前的线程数量大于core数量
         *            释放空闲的线程（maximumPoolSize-corePoolSize），只要线程空闲大于指定的keepAliveTime
         * 4、unit时间单位
         * 5、BlockingQueue<Runnable> workQueue,阻塞队列，如果任务很多，就会将多的任务保存到队列，只要线程空闲，就回去队列取出新的任务
         * 6、ThreadFactory threadFactory,线程的创建工厂
         * 7、RejectedExecutionHandler handler，如果队列满了，按照指定的拒绝策略拒绝执行任务
         *
         * 工作顺序：
         *运行流程：
         *1)、线程池创建，准备好core数量的核心线程，准备接受任务
         * 1.1core满了，就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
         * 1.2、阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         * 1.3、max满了就用RejectedExecutionHandLer拒绝任务
         * 1.4、max都执行完成，有很多空闲.在指定的时间keepAliveTime以后，释放max-core这些线程
         * new LinkedBLockingDeque<>():默认是Integer的最大值。内存不够
         *面试：
         * 一个线程池 core 7； max 20 ，queue：50，100 并发进来怎么分配的；
         * 先有 7 个能直接得到执行，接下来 50 个进入队列排队，在多开 13 个继续执行。现在 70 个
         * 被安排上了。剩下 30 个默认拒绝策略。
         */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5,
                200,
                30L
                ,TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());


//
//         executor.execute(new Runable01());
//         Future<Integer> submit = executor.submit(new Callable01());//submit可以获取返回值
//        System.out.println(submit.get()+"+++++");

//        System.out.println("main......start.....");
//         CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//             System.out.println("当前线程：" + Thread.currentThread().getId());
//             int i = 10 / 2;
//             System.out.println("运行结果：" + i);
//         }, executor);

        /**
         * 方法完成后的处理
         */
//         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//             System.out.println("当前线程：" + Thread.currentThread().getId());
//             int i = 10 / 0;
//             System.out.println("运行结果：" + i);
//             return i;
//         }, executor).whenComplete((res,exception) -> {
//             //虽然能得到异常信息，但是没法修改返回数据
//             System.out.println("异步任务成功完成了...结果是：" + res + "异常是：" + exception);
//         }).exceptionally(throwable -> {
//             //可以感知异常，同时返回默认值
//             return 666;
//         });
//        System.out.println("异常后返回数据："+future.get());
        /**
         * 方法执行完后端处理
         */
//         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//             System.out.println("当前线程：" + Thread.currentThread().getId());
//             int i = 10 / 2;
//             System.out.println("运行结果：" + i);
//             return i;
//         }, executor).handle((result,thr) -> {
//             if (result != null) {
//                 return result * 2;
//             }
//             if (thr != null) {
//                 System.out.println("异步任务成功完成了...结果是：" + result + "异常是：" + thr);
//                 return 0;
//             }
//             return 0;
//         });
//        System.out.println("handle后返回数据："+future.get());

        /**
         * 线程串行化
         * 1、thenRunL：不能获取上一步的执行结果
         * 2、thenAcceptAsync：能接受上一步结果，但是无返回值
         * 3、thenApplyAsync：能接受上一步结果，有返回值
         *
         */
//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executor).thenApplyAsync(res -> {
//            System.out.println("任务2启动了..." + res);
//            return "Hello" + res;
//        }, executor);
//        System.out.println("main......end....." + future.get());
/**##################################################################
 * 两个都完成
 */
//        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(()  ->{
//            System.out.println("任务1线程:" +Thread.currentThread().getId());
//            int i = 10 / 4;
//            System.out.println("任务1结束:");
//            return i;
//        },executor);
//        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务z线程:"+Thread.currentThread().getId());
//            System.out.println("任务2结束:" ) ;
//            return "He11o" ;
//        }, executor);
        //无法接收
//        future01.runAfterBothAsync(future02,()->{
//            System.out.println("任务3执行");
//        }, executor);
        //可接受，不可返回
//        future01.thenAcceptBothAsync(future02,(f1,f2)->{
//            System.out.println("任务3执行,之前结果: "+f1+"---"+f2);
//        }, executor);
        //可接受，可返回
//        CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
//            return f1 + "---" + f2;
//        }, executor);
//        System.out.println("返回值："+future.get());

/**##############################################################################################
 * 两个完成一个继续
 */
//            CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(()  ->{
//                System.out.println("任务1线程:" +Thread.currentThread().getId());
//                int i = 10 / 4;
//                System.out.println("任务1结束:");
//                return i;
//            },executor);
//            CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
//
//                try {
//                    Thread.sleep(3000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                System.out.println("任务z线程:"+Thread.currentThread().getId());
//                System.out.println("任务2结束:" ) ;
//                return "He11o" ;
//            }, executor);

//            //无法接收,无返回
//            future01.runAfterEitherAsync(future02, () -> {
//                System.out.println("任务3执行");
//            }, executor);

            //接收,无返回
//            future01.acceptEitherAsync(future02, (res) -> {
//                System.out.println("任务3执行,之前结果: "+res);
//
//            }, executor);

        //接收,返回
//        CompletableFuture<String> future = future01.applyToEitherAsync(future02, res -> res.toString(), executor);
//
//        System.out.println("+++++="+future.get());

/**################################################################################################
 * 多任务组合
 *
 */

        CompletableFuture<Object> futureImg = CompletableFuture.supplyAsync(()  ->{
            System.out.println("查询商品图片信息");

            return "hello.jpg";
        },executor);

        CompletableFuture<Object> futureAttr = CompletableFuture.supplyAsync(()  ->{

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询商品属性信息");
            return "黑色";
        },executor);

        CompletableFuture<Object> futureDesc = CompletableFuture.supplyAsync(()  ->{
            System.out.println("查询商品价格信息");

            return "500元";
        },executor);

//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureAttr, futureDesc, futureImg);
//        allOf.get();
//        System.out.println("end................"+futureAttr.get()+futureDesc.get()+futureImg.get());
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureAttr, futureDesc, futureImg);
        anyOf.get();
        System.out.println("end................"+ anyOf.get());

//        ExecutorService executor = Executors.newCachedThreadPool();
//        Future<Integer> submit = executor.submit(() -> {
//            int a = 2;
//            // 这边执行具体的方法
//            try {
//                System.out.println("fff");
//            } catch (Exception exception) {
//                exception.printStackTrace();
//            }
//            return a;
//        });
//        System.out.println(submit.get());
//        executor.shutdown();

    }

    private static void threadPool() {

        ExecutorService threadPool = new ThreadPoolExecutor(
                200,
                10,
                10L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        //定时任务的线程池
        ExecutorService executor = Executors.newScheduledThreadPool(2);
    }

    /**
     * 继承Thread
     * 实现Runnable接口
     * 实现caLLabLe接口 + FutureTask (可以章到返回结果，可以处理异常)
     * 线程池中（可以控制资源）
     * Future可以获取到异步结果
     */

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }


    public static class Runable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }


    public static class Callable01 implements Callable<Integer> {//返回值
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }
    }
}
